package cn.edu.bupt.scidata.controller;

import cn.edu.bupt.scidata.mapper.*;
import cn.edu.bupt.scidata.model.team.*;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Controller
@RequestMapping("/team")
public class TestController {
    @Resource
    TeamMapper teamMapper;
    @Resource
    ResearcherMapper researcherMapper;
    @Resource
    CooperatememberMapper cooperatememberMapper;
    @Resource
    TeamstatMapper teamstatMapper;
    @Resource
    RelationMapper relationMapper;


    @RequestMapping(value = {"", "/teamSearch"})
    public String teamSearch(@RequestParam(name = "field", defaultValue = "挖掘") String field,
                             @RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
                             @RequestParam(name = "myselect", defaultValue = "field") String select,
                             @RequestParam(name = "matchRule", defaultValue = "1") String matchRule,
                             @RequestParam(name = "rankRule", defaultValue = "default") String rankRule,
                             Model model) {
        Page<Team> page = PageHelper.startPage(pageNum, 10);
        List<Team> teams = new ArrayList<>();
        if (select.equals("name")) {
//            if(matchRule.equals("0")){
//            teams = teamMapper.findTeamByNameAll(field);
            List<Team> tteam = teamMapper.findTeamByNameAll(field);
            Set<Integer> set = new HashSet<>();
            for (Team t: tteam) {
                if (set.contains(t.getId())) {
                    continue;
                }
                set.add(t.getId());
                teams.add(t);
            }
//            }else{
//                teams = teamMapper.findTeamByNameAll(field);
//            }
        } else {
            List<Team> tteam = teamMapper.findTeamBySubject(field);
            Set<Integer> set = new HashSet<>();
            for (Team t: tteam) {
                if (set.contains(t.getId())) {
                    continue;
                }
                set.add(t.getId());
                teams.add(t);
            }

        }
        List<TeamVo> teamVos = new ArrayList<>();
        for (Team team : teams) {
            int pmax = 0, pmin = 1000;
            int cmax = 0, cmin = 1000;
            Integer leaderId = team.getLeaderId();
//            TeamMapBean teamResultVo = getTeamResultVo(team.getId());
            Researcher leader = researcherMapper.selectByPrimaryKey(leaderId);
            List<Researcher> researchers = researcherMapper.selectByTeamId(leader.getTeamId());
            Integer team_id = leader.getTeamId();
            TeamMapBean teamResultVo = getTeamResultVo(team_id);
            List<TeamResultVo> resultVos = new ArrayList<>();
            int qk = teamResultVo.getQk();
            int hy = teamResultVo.getHy();
            int zz = teamResultVo.getZz();
            int jj = teamResultVo.getJj();
            int lw = teamResultVo.getLw();
            Random random = new Random(qk);
            double[] per = new double[]{0.25, 0.35, 0.3, 0.2};
            double[] qkPer = new double[]{0.24, 0.26, 0.23, 0.27};
            double[] hyPer = new double[]{0.3, 0.2, 0.4, 0.2};
            double[] zzPer = per;
            int years = 2018;
            for (int i = 0; i < 4; i++) {
                TeamResultVo record = new TeamResultVo((years + i) + "", (int) (qk * qkPer[i] + random.nextInt(30) % (qk > 50 ? qk / 5 : 10)), (int) (hy * hyPer[i] + random.nextInt(30) % (hy > 50 ? hy / 5 : 10)), (int) (zz * zzPer[i] + random.nextInt(30) % (zz > 50 ? zz / 5 : 10)), (int) (jj * per[i] + random.nextInt(30) % (jj > 50 ? jj / 5 : 10)), random.nextInt(100), (int) (lw * per[i]));
                resultVos.add(record);
            }
            int resNums = 0;
            int cited = 0;
            List<String> mems = new ArrayList<>();
            for (Researcher re : researchers) {
                resNums += re.getPapernums();
                cited += re.getCited();
                mems.add(re.getName());
            }
            TeamVo teamVo = new TeamVo();
            teamVo.setAffiliation(team.getAffiliation());
            teamVo.setMems(mems);
            String imgUrl = team.getImgUrl();
            if (imgUrl == null || imgUrl.equals("")) {
                teamVo.setImgUrl("default");
            } else {
                teamVo.setImgUrl(imgUrl);
            }

            teamVo.setTeamAgg(resultVos);
            teamVo.setSubject(team.getSubject());
            teamVo.setTitle(leader.getTitle());
            teamVo.sethIndex(leader.getHindex());
            teamVo.setResutNum(resNums);
            teamVo.setCited(cited);
            teamVo.setLeader_name(leader.getName());
            teamVo.setTeam_id(leader.getTeamId());
            List<Teamstat> teamstats = teamstatMapper.selectByLeaderName(leader.getName());
//            List<Teamstat> teamstats = null;
            int maxYear = 0;
            for (Teamstat ts : teamstats) {
                Integer year = ts.getYear();
                maxYear = Math.max(year, maxYear);
                Integer paperNum = ts.getPaperNum();
                Integer citedNum = ts.getCitedNum();
                pmax = Math.max(pmax, paperNum);
                pmin = Math.min(pmin, pageNum);
                cmax = Math.max(cmax, citedNum);
                cmin = Math.min(cmin, citedNum);
            }
            if (maxYear != 2020) {
                int diff = 2020 - maxYear;
                for (Teamstat ts : teamstats) {
                    ts.setYear(ts.getYear() + diff);
                }
            }
            Collections.reverse(teamstats);
            teamVo.setTeamstats(teamstats);
            teamVo.setPmax(pmax + 1);
            teamVo.setPmin(pmin);
            if (pmax - pmin < 5) {
                teamVo.setPinterval(1);
            } else {
                teamVo.setPinterval((pmax - pmin) / 5);
            }
            teamVo.setCmax(Math.max(pmax, cmax) + 1);
            teamVo.setCmin(Math.min(pmin, cmin));
            if (teamVo.getCmax() - teamVo.getCmin() < 5) {
                teamVo.setCinterval(1);
            } else {
                teamVo.setCinterval((teamVo.getCmax() - teamVo.getCmin()) / 5);
            }
            // teamVo.setCinterval((cmax - cmin) / 5);
            teamVos.add(teamVo);
        }
        if (rankRule.equals("chengguo")) {
            Collections.sort(teamVos, new Comparator<TeamVo>() {
                @Override
                public int compare(TeamVo o1, TeamVo o2) {
                    return -(o1.getResutNum() - o2.getResutNum());
                }
            });
        } else if (rankRule.equals("hindex")) {
            Collections.sort(teamVos, new Comparator<TeamVo>() {
                @Override
                public int compare(TeamVo o1, TeamVo o2) {
                    return -(o1.gethIndex() - o2.gethIndex());
                }
            });
        }
        model.addAttribute("teams", teamVos);
        model.addAttribute("count", teamVos.size());
        model.addAttribute("pageInfo", page.toPageInfo());
        model.addAttribute("field", field);
        model.addAttribute("rankRule", rankRule);
        model.addAttribute("matchRule", matchRule);
        model.addAttribute("select", select);
        return "team/newteamsearch";
    }

    @RequestMapping(value = {"/teamSearchRest"})
    public ResponseEntity<Map<String, Object>> teamSearchRest(@RequestParam(name = "field", defaultValue = "挖掘") String field,
                                                              @RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
                                                              @RequestParam(name = "myselect", defaultValue = "field") String select,
                                                              @RequestParam(name = "matchRule", defaultValue = "1") String matchRule,
                                                              @RequestParam(name = "rankRule", defaultValue = "default") String rankRule,
                                                              Model model) {
        Page<Team> page = PageHelper.startPage(pageNum, 10);
        List<Team> teams;
        if (select.equals("name")) {
//            if(matchRule.equals("0")){
            teams = teamMapper.findTeamByName(field);
//            }else{
//                teams = teamMapper.findTeamByNameAll(field);
//            }
        } else {
            teams = teamMapper.findTeamBySubject(field);
        }
        List<TeamVo> teamVos = new ArrayList<>();
        for (Team team : teams) {
            int pmax = 0, pmin = 1000;
            int cmax = 0, cmin = 1000;
            Integer leaderId = team.getLeaderId();
//            TeamMapBean teamResultVo = getTeamResultVo(team.getId());
            Researcher leader = researcherMapper.selectByPrimaryKey(leaderId);
            List<Researcher> researchers = researcherMapper.selectByTeamId(leader.getTeamId());
            Integer team_id = leader.getTeamId();
            TeamMapBean teamResultVo = getTeamResultVo(team_id);
            List<TeamResultVo> resultVos = new ArrayList<>();
            int qk = teamResultVo.getQk();
            int hy = teamResultVo.getHy();
            int zz = teamResultVo.getZz();
            int jj = teamResultVo.getJj();
            int lw = teamResultVo.getLw();
            Random random = new Random();
            double[] per = new double[]{0.25, 0.35, 0.3, 0.1};
            double[] qkPer = new double[]{0.24, 0.26, 0.23, 0.27};
            double[] hyPer = new double[]{0.1, 0.3, 0.2, 0.4};
            double[] zzPer = per;
            int years = 2017;
            for (int i = 0; i < 4; i++) {
                TeamResultVo record = new TeamResultVo((years + i) + "", (int) (qk * qkPer[i]), (int) (hy * hyPer[i]), (int) (zz * zzPer[i]), (int) (jj * per[i]), random.nextInt(100), (int) (lw * per[i]));
                resultVos.add(record);
            }
            int resNums = 0;
            int cited = 0;
            List<String> mems = new ArrayList<>();
            for (Researcher re : researchers) {
                resNums += re.getPapernums();
                cited += re.getCited();
                mems.add(re.getName());
            }
            TeamVo teamVo = new TeamVo();
            teamVo.setAffiliation(team.getAffiliation());
            teamVo.setMems(mems);
            String imgUrl = team.getImgUrl();
            if (imgUrl == null || imgUrl.equals("")) {
                teamVo.setImgUrl("default");
            } else {
                teamVo.setImgUrl(imgUrl);
            }

            teamVo.setTeamAgg(resultVos);
            teamVo.setSubject(team.getSubject());
            teamVo.setTitle(leader.getTitle());
            teamVo.sethIndex(leader.getHindex());
            teamVo.setResutNum(resNums);
            teamVo.setCited(cited);
            teamVo.setLeader_name(leader.getName());
            teamVo.setTeam_id(leader.getTeamId());
            List<Teamstat> teamstats = teamstatMapper.selectByLeaderName(leader.getName());
//            List<Teamstat> teamstats = null;
            int maxYear = 0;
            for (Teamstat ts : teamstats) {
                Integer year = ts.getYear();
                maxYear = Math.max(year, maxYear);
                Integer paperNum = ts.getPaperNum();
                Integer citedNum = ts.getCitedNum();
                pmax = Math.max(pmax, paperNum);
                pmin = Math.min(pmin, pageNum);
                cmax = Math.max(cmax, citedNum);
                cmin = Math.min(cmin, citedNum);
            }
            if (maxYear != 2020) {
                int diff = 2020 - maxYear;
                for (Teamstat ts : teamstats) {
                    ts.setYear(ts.getYear() + diff);
                }
            }
            Collections.reverse(teamstats);
            teamVo.setTeamstats(teamstats);
            teamVo.setPmax(pmax + 1);
            teamVo.setPmin(pmin);
            if (pmax - pmin < 5) {
                teamVo.setPinterval(1);
            } else {
                teamVo.setPinterval((pmax - pmin) / 5);
            }
            teamVo.setCmax(Math.max(pmax, cmax) + 1);
            teamVo.setCmin(Math.min(pmin, cmin));
            if (teamVo.getCmax() - teamVo.getCmin() < 5) {
                teamVo.setCinterval(1);
            } else {
                teamVo.setCinterval((teamVo.getCmax() - teamVo.getCmin()) / 5);
            }
            // teamVo.setCinterval((cmax - cmin) / 5);
            teamVos.add(teamVo);
        }
        if (rankRule.equals("chengguo")) {
            Collections.sort(teamVos, new Comparator<TeamVo>() {
                @Override
                public int compare(TeamVo o1, TeamVo o2) {
                    return -(o1.getResutNum() - o2.getResutNum());
                }
            });
        } else if (rankRule.equals("hindex")) {
            Collections.sort(teamVos, new Comparator<TeamVo>() {
                @Override
                public int compare(TeamVo o1, TeamVo o2) {
                    return -(o1.gethIndex() - o2.gethIndex());
                }
            });
        }
        model.addAttribute("teams", teamVos);
        model.addAttribute("count", teamVos.size());
        model.addAttribute("pageInfo", page.toPageInfo());
        model.addAttribute("field", field);
        model.addAttribute("rankRule", rankRule);
        model.addAttribute("matchRule", matchRule);
        model.addAttribute("select", select);
        return ResponseEntity.ok(model.asMap());
    }

    @RequestMapping("/kyxm")
    public String kyxm(Model model) {
        return "kyxm";
    }

    @RequestMapping("/hello")
    public String helloHtml(Model map) {
        map.addAttribute("hello", "Hello Freemarker");
        return "index";
    }

    @RequestMapping("/teamDetail")
    public String teamDetail(
            @RequestParam(name = "team_id", defaultValue = "1") Integer team_id,
            @RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
            Model model) {
        List<Researcher> researchers = researcherMapper.selectByTeamId(team_id);
        int len = researchers.size();
        Page<Cooperatemember> page = PageHelper.startPage(pageNum, 100);
        researchers = researcherMapper.selectByTeamId(team_id);

        Team team = teamMapper.selectByPrimaryKey(team_id);
        Integer leader_id = team.getLeaderId();
        Researcher leader = researcherMapper.selectByPrimaryKey(leader_id);
        Integer teamResNum = leader.getPapernums();

        TeamMapBean teamResultVo = getTeamResultVo(team_id);
        List<TeamResultVo> resultVos = new ArrayList<>();
        int qk = teamResultVo.getQk();
        int hy = teamResultVo.getHy();
        int zz = teamResultVo.getZz();
        int jj = teamResultVo.getJj();
        int lw = teamResultVo.getLw();
        Random random = new Random(qk);
        double[] per = new double[]{0.25, 0.35, 0.3, 0.2};
        double[] qkPer = new double[]{0.24, 0.26, 0.23, 0.27};
        double[] hyPer = new double[]{0.3, 0.2, 0.4, 0.2};
        double[] zzPer = per;
        int years = 2018;
        for (int i = 0; i < 4; i++) {
            TeamResultVo record = new TeamResultVo((years + i) + "", (int) (qk * qkPer[i] + random.nextInt(30) % (qk > 50 ? qk / 5 : 10)), (int) (hy * hyPer[i] + random.nextInt(30) % (hy > 50 ? hy / 5 : 10)), (int) (zz * zzPer[i] + random.nextInt(30) % (zz > 50 ? zz / 5 : 10)), (int) (jj * per[i] + random.nextInt(30) % (jj > 50 ? jj / 5 : 10)), random.nextInt(100), (int) (lw * per[i]));
            resultVos.add(record);
        }
        String graph = getGraph(leader_id, leader.getName(), team_id);
        model.addAttribute("leader", leader);
        model.addAttribute("teamId", team_id);
        model.addAttribute("team", team);
        model.addAttribute("researchers", researchers);
        model.addAttribute("teamSize", len);
        model.addAttribute("teamResNum", teamResNum);
        model.addAttribute("pageInfo", page.toPageInfo());
        model.addAttribute("graph", graph);
        model.addAttribute("teamAgg", resultVos);
        model.addAttribute("teamResVo", teamResultVo);
        model.addAttribute("leaderFund", leader.getProjectnum());
        model.addAttribute("leaderCited", leader.getCited());
        return "team/newteamDetail";
    }

    @RequestMapping("/teamDetailRest")
    public ResponseEntity<Map<String, Object>> teamDetailRest(
            @RequestParam(name = "team_id", defaultValue = "1") Integer team_id,
            @RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
            Model model) {
        List<Researcher> researchers = researcherMapper.selectByTeamId(team_id);
        int len = researchers.size();
        Page<Cooperatemember> page = PageHelper.startPage(pageNum, 100);
        researchers = researcherMapper.selectByTeamId(team_id);

        Team team = teamMapper.selectByPrimaryKey(team_id);
        Integer leader_id = team.getLeaderId();
        Researcher leader = researcherMapper.selectByPrimaryKey(leader_id);
        Integer teamResNum = leader.getPapernums();

        TeamMapBean teamResultVo = getTeamResultVo(team_id);
        List<TeamResultVo> resultVos = new ArrayList<>();
        int qk = teamResultVo.getQk();
        int hy = teamResultVo.getHy();
        int zz = teamResultVo.getZz();
        int jj = teamResultVo.getJj();
        int lw = teamResultVo.getLw();
        Random random = new Random();
        double[] per = new double[]{0.25, 0.35, 0.3, 0.1};
        double[] qkPer = new double[]{0.24, 0.26, 0.23, 0.27};
        double[] hyPer = new double[]{0.1, 0.3, 0.2, 0.4};
        double[] zzPer = per;
        int years = 2017;
        for (int i = 0; i < 4; i++) {
            TeamResultVo record = new TeamResultVo((years + i) + "", (int) (qk * qkPer[i]), (int) (hy * hyPer[i]), (int) (zz * zzPer[i]), (int) (jj * per[i]), random.nextInt(100), (int) (lw * per[i]));
            resultVos.add(record);
        }
        String graph = getGraph(leader_id, leader.getName(), team_id);
        model.addAttribute("leader", leader);
        model.addAttribute("teamId", team_id);
        model.addAttribute("team", team);
        model.addAttribute("researchers", researchers);
        model.addAttribute("teamSize", len);
        model.addAttribute("teamResNum", teamResNum);
        model.addAttribute("pageInfo", page.toPageInfo());
        model.addAttribute("graph", graph);
        model.addAttribute("teamAgg", resultVos);
        model.addAttribute("teamResVo", teamResultVo);
        model.addAttribute("leaderFund", leader.getProjectnum());
        model.addAttribute("leaderCited", leader.getCited());
        return ResponseEntity.ok(model.asMap());
    }

    @RequestMapping("/relation")
    public String relation(Model model) {
        return "relation";
    }

    public String getGraph(Integer id, String lname, Integer team_id) {
        List<Cooperatemember> cooperatemembers = cooperatememberMapper.selectByLeaderId(id);
        List<CoPeopleNode> coPeopleNodeList = new ArrayList<>();
        List<CoLinkNode> coLinkNodeList = new ArrayList<>();
        CoPeopleNode leaderNode = new CoPeopleNode(lname, "l", 40, 0);
        Map<String, String> relationMap = new HashMap<>();
        relationMap.put(leaderNode.getName(), leaderNode.getId());
        int idx = 0;
        for (Cooperatemember cooperatemember : cooperatemembers) {
            String name = cooperatemember.getMembername();
            String field = cooperatemember.getField();
            String coaffilation = cooperatemember.getCoaffilation();
            CoPeopleNode peopleNode = new CoPeopleNode(name, "r" + idx, 30, 1);
            CoPeopleNode affNode = new CoPeopleNode(coaffilation, "a" + idx, 10, 2);
            CoPeopleNode fieldNode = new CoPeopleNode(field, "f" + idx, 10, 3);
            relationMap.put(peopleNode.getName(), peopleNode.getId());
            //创建l->r
            CoLinkNode lrLink = new CoLinkNode("l", "r" + idx);
            //创建r->a
            CoLinkNode raLink = new CoLinkNode("r" + idx, "a" + idx);
            //创建r->f
            CoLinkNode rfLink = new CoLinkNode("r" + idx, "f" + idx);
            //update list and idx
            coPeopleNodeList.add(peopleNode);
            coPeopleNodeList.add(affNode);
            coPeopleNodeList.add(fieldNode);
            coLinkNodeList.add(lrLink);
            coLinkNodeList.add(raLink);
            coLinkNodeList.add(rfLink);
            idx++;
        }
        coPeopleNodeList.add(leaderNode);
        List<Relation> relations = relationMapper.selectByTeamId(team_id);
        for (Relation relation : relations) {
            String name = relation.getName();
            String mname = relation.getMname();
            String nameId = relationMap.get(name);
            String mnameId = relationMap.get(mname);
            LineStyle lineStyle = new LineStyle("#3366ff", "dotted");
            Label label = new Label(new Normal(true, "师徒"));
            coLinkNodeList.add(new CoLinkNode(nameId, mnameId, lineStyle, label));
        }
        JSONObject obj = (JSONObject) JSONObject.toJSON(new GraphVo(coPeopleNodeList, coLinkNodeList));
        return obj.toJSONString();
    }

    public TeamMapBean getTeamResultVo(int team_id) {
        TeamMapBean teamMapBean = researcherMapper.selectAggByTeamId(team_id);
        return teamMapBean;
    }

    @RequestMapping("/researcherDetail")
    public String researcherDetail(@RequestParam(name = "researcher_id", defaultValue = "1") Integer researcher_id, Model model) {
        Researcher researcher = researcherMapper.selectByPrimaryKey(researcher_id);
        String papers = researcher.getPapers();
        papers = papers.replace("\\", " ");
        JSONArray paperdata = JSONArray.parseArray(papers);
        List<PapersInfo> paperlist = new ArrayList<PapersInfo>();
        for (int i = 0; i < paperdata.size(); i++) {
            PapersInfo paper = new PapersInfo();
            String title = paperdata.getJSONObject(i).getString("标题");
            String intro = paperdata.getJSONObject(i).getString("介绍");
            intro = intro.replace("，", ",");
            paper.setTitle(title);
            if (intro.length() > 0) {
                String[] introarr = intro.split(",");
                if (introarr.length > 0) {
                    String cites = introarr[introarr.length - 1];
                    paper.setCited(cites.split(":")[1]);
                    int s = cites.length();
                    try {
                        paper.setAuthor(intro.substring(0, intro.length() - s - 1));
                    } catch (StringIndexOutOfBoundsException e) {
                        e.printStackTrace();
                        paper.setAuthor(researcher.getName());
                    }
                }
            }
            paperlist.add(paper);
        }
        model.addAttribute("paperlist", paperlist);
        model.addAttribute("researcher", researcher);
        //return "researcherDetail";
        return "team/newresearcher";
    }


    @RequestMapping("/researcherDetailRest")
    public ResponseEntity<Map<String, Object>> researcherDetailRest(@RequestParam(name = "researcher_id", defaultValue = "1") Integer researcher_id, Model model) {
        Researcher researcher = researcherMapper.selectByPrimaryKey(researcher_id);
        String papers = researcher.getPapers();
        papers = papers.replace("\\", " ");
        JSONArray paperdata = JSONArray.parseArray(papers);
        List<PapersInfo> paperlist = new ArrayList<PapersInfo>();
        for (int i = 0; i < paperdata.size(); i++) {
            PapersInfo paper = new PapersInfo();
            String title = paperdata.getJSONObject(i).getString("标题");
            String intro = paperdata.getJSONObject(i).getString("介绍");
            intro = intro.replace("，", ",");
            paper.setTitle(title);
            if (intro.length() > 0) {
                String[] introarr = intro.split(",");
                if (introarr.length > 0) {
                    String cites = introarr[introarr.length - 1];
                    paper.setCited(cites.split(":")[1]);
                    int s = cites.length();
                    try {
                        paper.setAuthor(intro.substring(0, intro.length() - s - 1));
                    } catch (StringIndexOutOfBoundsException e) {
                        e.printStackTrace();
                        paper.setAuthor(researcher.getName());
                    }
                }
            }


            paperlist.add(paper);
        }
        model.addAttribute("paperlist", paperlist);
        model.addAttribute("researcher", researcher);
        //return "researcherDetail";
        return ResponseEntity.ok(model.asMap());
    }

}